10분 안에 C 배우기
C는 효율성과 하드웨어에 가까운 기능으로 유명한 강력한 범용 프로그래밍 언어입니다. 이 튜토리얼은 C 프로그래밍의 기초를 다루며 언어를 빠르게 이해할 수 있도록 도와줍니다.
1. 첫 번째 C 프로그램 작성하기
클래식한 “Hello, World!” 프로그램부터 시작해보겠습니다. hello.c
라는 파일을 생성하고 다음 코드를 입력하세요:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
파일을 저장하고 GCC 같은 C 컴파일러를 사용하여 컴파일하세요:
gcc hello.c -o hello
./hello
출력 결과는 다음과 같습니다:
Hello, World!
이 간단한 프로그램은 C의 기본 구조를 보여줍니다:
#include <stdio.h>
는 표준 입출력 라이브러리를 포함합니다int main()
은 프로그램의 진입점입니다printf()
는 텍스트 출력을 표시합니다return 0
은 성공적인 실행을 나타냅니다
2. 기본 문법
C는 구조화된 문법을 사용하며 세미콜론으로 문장을 종료하고 중괄호 {}
로 코드 블록을 정의합니다.
// 이것은 한 줄 주석입니다
/* 이것은 여러 줄 주석입니다 */
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
C의 기본 문법 규칙:
- 세미콜론: 모든 문장은 세미콜론
;
으로 끝나야 합니다 - 주석: 한 줄 주석은
//
를 사용하고, 여러 줄 주석은/* */
를 사용합니다 - 코드 블록: 중괄호
{}
로 정의됩니다 - 대소문자 구분: C는 대소문자를 구분합니다 (
main
vsMain
)
3. 변수와 데이터 타입
C는 정적 타입 언어로, 사용하기 전에 변수 타입을 선언해야 합니다.
기본 변수 명명 규칙:
- 변수 이름은 문자, 숫자, 밑줄을 포함할 수 있습니다
- 변수 이름은 숫자로 시작할 수 없습니다
- 변수 이름은 대소문자를 구분합니다
- C 키워드는 변수 이름으로 사용할 수 없습니다
C의 주요 데이터 타입:
- int: 정수 (예:
42
,-10
) - float: 부동 소수점 숫자 (예:
3.14
,-2.5
) - double: 배정밀도 부동 소수점 숫자
- char: 단일 문자 (예:
'A'
,'z'
) - void: 타입 없음
int age = 25;
float temperature = 36.5;
double pi = 3.14159265359;
char grade = 'A';
3.1 정수 타입
C는 다양한 크기의 여러 정수 타입을 제공합니다:
char small_number = 100; // 보통 1바이트
short medium_number = 32000; // 보통 2바이트
int regular_number = 1000000; // 보통 4바이트
long large_number = 1000000000; // 보통 4 또는 8바이트
3.2 부동 소수점 타입
float single_precision = 3.14f;
double double_precision = 3.14159265359;
long double extended_precision = 3.14159265358979323846L;
3.3 문자 타입
문자는 ASCII 인코딩을 사용하여 정수로 저장됩니다:
char letter = 'A';
char digit = '7';
char newline = '\n';
char tab = '\t';
4. 상수
상수는 프로그램 실행 중에 변경할 수 없는 고정된 값입니다:
const int MAX_SIZE = 100;
const float PI = 3.14159;
const char NEWLINE = '\n';
#define MAX_USERS 1000
#define PI 3.14159
5. 입력과 출력
C는 입력과 출력 작업을 위해 stdio.h
의 함수들을 사용합니다.
5.1 printf()로 출력하기
#include <stdio.h>
int main() {
int age = 25;
float height = 1.75;
char name[] = "John";
printf("Hello, %s!\n", name);
printf("You are %d years old\n", age);
printf("Your height is %.2f meters\n", height);
return 0;
}
일반적인 형식 지정자:
%d
- 정수%f
- float/double%c
- 문자%s
- 문자열%p
- 포인터
5.2 scanf()로 입력받기
#include <stdio.h>
int main() {
int age;
float height;
char name[50];
printf("Enter your name: ");
scanf("%s", name);
printf("Enter your age: ");
scanf("%d", &age);
printf("Enter your height: ");
scanf("%f", &height);
printf("Hello %s, you are %d years old and %.2f meters tall\n",
name, age, height);
return 0;
}
6. 연산자
C는 다양한 계산을 위한 풍부한 연산자 집합을 제공합니다.
6.1 산술 연산자
int a = 10, b = 3;
printf("Addition: %d\n", a + b); // 13
printf("Subtraction: %d\n", a - b); // 7
printf("Multiplication: %d\n", a * b); // 30
printf("Division: %d\n", a / b); // 3
printf("Modulus: %d\n", a % b); // 1
6.2 비교 연산자
int x = 5, y = 10;
printf("Equal: %d\n", x == y); // 0 (false)
printf("Not equal: %d\n", x != y); // 1 (true)
printf("Greater than: %d\n", x > y); // 0
printf("Less than: %d\n", x < y); // 1
6.3 논리 연산자
int a = 1, b = 0;
printf("AND: %d\n", a && b); // 0
printf("OR: %d\n", a || b); // 1
printf("NOT: %d\n", !a); // 0
6.4 비트 연산자
unsigned int a = 5; // 2진수로 0101
unsigned int b = 3; // 2진수로 0011
printf("AND: %d\n", a & b); // 1 (0001)
printf("OR: %d\n", a | b); // 7 (0111)
printf("XOR: %d\n", a ^ b); // 6 (0110)
printf("NOT: %d\n", ~a); // 시스템에 따라 다름
printf("Left shift: %d\n", a << 1); // 10 (1010)
printf("Right shift: %d\n", a >> 1); // 2 (0010)
7. 제어 흐름
C는 프로그램 실행을 관리하기 위한 여러 제어 흐름 문을 제공합니다.
7.1 if 문
int age = 20;
if (age >= 18) {
printf("Adult\n");
} else if (age >= 13) {
printf("Teen\n");
} else {
printf("Child\n");
}
7.2 switch 문
int day = 3;
switch (day) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
default:
printf("Other day\n");
}
7.3 for 루프
for (int i = 0; i < 5; i++) {
printf("i = %d\n", i);
}
7.4 while 루프
int count = 0;
while (count < 5) {
printf("Count: %d\n", count);
count++;
}
7.5 do-while 루프
int count = 0;
do {
printf("Count: %d\n", count);
count++;
} while (count < 5);
7.6 break와 continue
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // 루프 종료
}
if (i % 2 == 0) {
continue; // 짝수 건너뛰기
}
printf("i = %d\n", i); // 출력: 1, 3
}
8. 배열
배열은 같은 타입의 여러 값을 저장합니다.
8.1 1차원 배열
int numbers[5] = {1, 2, 3, 4, 5};
// 요소 접근
printf("First element: %d\n", numbers[0]);
printf("Last element: %d\n", numbers[4]);
// 요소 수정
numbers[0] = 10;
// 배열 순회
for (int i = 0; i < 5; i++) {
printf("numbers[%d] = %d\n", i, numbers[i]);
}
8.2 다차원 배열
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
// 요소 접근
printf("matrix[1][2] = %d\n", matrix[1][2]); // 6
// 2차원 배열 순회
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
9. 문자열
C에서 문자열은 널 문자 \0
로 종료되는 문자 배열입니다.
char greeting[] = "Hello"; // 자동으로 널 종결자 포함
char name[20] = "John";
// string.h의 문자열 함수
#include <string.h>
char str1[20] = "Hello";
char str2[20] = "World";
printf("Length: %lu\n", strlen(str1)); // 5
strcpy(str1, str2); // str2를 str1에 복사
printf("After copy: %s\n", str1); // World
if (strcmp(str1, str2) == 0) {
printf("Strings are equal\n");
}
10. 함수
함수는 특정 작업을 수행하는 재사용 가능한 코드 블록입니다.
10.1 함수 정의와 호출
#include <stdio.h>
// 함수 선언
int add(int a, int b);
int main() {
int result = add(5, 3);
printf("5 + 3 = %d\n", result);
return 0;
}
// 함수 정의
int add(int a, int b) {
return a + b;
}
10.2 반환 값이 없는 함수
void greet(char name[]) {
printf("Hello, %s!\n", name);
}
int main() {
greet("Alice");
return 0;
}
10.3 재귀 함수
int factorial(int n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
printf("5! = %d\n", factorial(5)); // 120
return 0;
}
11. 포인터
포인터는 메모리 주소를 저장하는 변수입니다.
11.1 기본 포인터 사용법
int number = 42;
int *ptr = &number; // ptr은 number의 주소를 저장
printf("Value: %d\n", number); // 42
printf("Address: %p\n", &number); // 메모리 주소
printf("Pointer value: %d\n", *ptr); // 42 (역참조)
// 포인터를 통해 값 수정
*ptr = 100;
printf("New value: %d\n", number); // 100
11.2 포인터와 배열
int numbers[] = {1, 2, 3, 4, 5};
int *ptr = numbers; // 첫 번째 요소를 가리킴
printf("First element: %d\n", *ptr); // 1
printf("Second element: %d\n", *(ptr + 1)); // 2
// 배열 이름은 기본적으로 첫 번째 요소를 가리키는 포인터입니다
for (int i = 0; i < 5; i++) {
printf("numbers[%d] = %d\n", i, *(numbers + i));
}
11.3 포인터와 함수
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 5, y = 10;
printf("Before swap: x=%d, y=%d\n", x, y);
swap(&x, &y);
printf("After swap: x=%d, y=%d\n", x, y);
return 0;
}
12. 구조체
구조체는 관련된 변수들을 함께 그룹화할 수 있게 해줍니다.
12.1 구조체 정의와 사용
#include <stdio.h>
#include <string.h>
// 구조체 정의
struct Student {
char name[50];
int age;
float gpa;
};
int main() {
// 구조체 변수 생성
struct Student student1;
// 값 할당
strcpy(student1.name, "Alice");
student1.age = 20;
student1.gpa = 3.8;
// 구조체 멤버 접근
printf("Name: %s\n", student1.name);
printf("Age: %d\n", student1.age);
printf("GPA: %.2f\n", student1.gpa);
return 0;
}
12.2 포인터와 구조체
struct Point {
int x;
int y;
};
int main() {
struct Point p1 = {10, 20};
struct Point *ptr = &p1;
printf("Coordinates: (%d, %d)\n", ptr->x, ptr->y);
return 0;
}
13. 동적 메모리 할당
C는 동적 메모리 관리를 위한 함수들을 제공합니다.
13.1 malloc, calloc, realloc, free
#include <stdio.h>
#include <stdlib.h>
int main() {
// 5개의 정수를 위한 메모리 할당
int *numbers = (int*)malloc(5 * sizeof(int));
if (numbers == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
// 배열 초기화
for (int i = 0; i < 5; i++) {
numbers[i] = i * 10;
}
// 배열 출력
for (int i = 0; i < 5; i++) {
printf("numbers[%d] = %d\n", i, numbers[i]);
}
// 할당된 메모리 해제
free(numbers);
return 0;
}
13.2 동적 문자열 할당
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *name = (char*)malloc(50 * sizeof(char));
if (name != NULL) {
strcpy(name, "Dynamic string");
printf("Name: %s\n", name);
free(name);
}
return 0;
}
14. 파일 작업
C는 파일 읽기와 쓰기를 위한 함수들을 제공합니다.
14.1 파일에 쓰기
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "w");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
fprintf(file, "Hello, File!\n");
fprintf(file, "This is a test.\n");
fclose(file);
printf("File written successfully.\n");
return 0;
}
14.2 파일에서 읽기
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
char buffer[100];
while (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("%s", buffer);
}
fclose(file);
return 0;
}
15. 전처리기 지시문
전처리기 지시문은 컴파일 전에 처리됩니다.
15.1 #include
#include <stdio.h> // 시스템 헤더 파일
#include "myheader.h" // 사용자 헤더 파일
15.2 #define
#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main() {
double area = PI * 5 * 5;
int larger = MAX(10, 20);
printf("Area: %.2f\n", area);
printf("Larger number: %d\n", larger);
return 0;
}
15.3 조건부 컴파일
#define DEBUG 1
int main() {
#ifdef DEBUG
printf("Debug mode enabled\n");
#endif
#if DEBUG == 1
printf("Debug level 1\n");
#elif DEBUG == 2
printf("Debug level 2\n");
#else
printf("No debug\n");
#endif
return 0;
}
16. 오류 처리
C는 내장된 예외 처리가 없으므로 반환 값과 오류 코드를 사용합니다.
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
printf("Error opening file: %s\n", strerror(errno));
return 1;
}
fclose(file);
return 0;
}
이 포괄적인 C 튜토리얼은 C 프로그래밍을 시작하는 데 필요한 필수 개념들을 다룹니다. 이 예제들을 연습하고 언어에 더 익숙해지면 연결 리스트, 함수 포인터, 다중 파일 프로그램과 같은 더 고급 주제들을 탐구해보세요.